const [mediaNode, setMediaNode] = useState()
const [jsNode, setjsNode] = useState()
const [mediaStream, setM] = useState()
function record() {
    window.navigator.mediaDevices.getUserMedia({
        audio: true
    }).then(mediaStream => {
        beginRecord(mediaStream);
        setM(mediaStream)
    }).catch(err => {
        // 如果用户电脑没有麦克风设备或者用户拒绝了，或者连接出问题了等
        // 这里都会抛异常，并且通过err.name可以知道是哪种类型的错误 
        console.error(err);
    });
}
function beginRecord(mediaStream) {
    let audioContext = new (window.AudioContext || window.webkitAudioContext);
    let mediaNode = audioContext.createMediaStreamSource(mediaStream);

    setMediaNode(mediaNode)
    // 创建一个jsNode
    let jsNode = createJSNode(audioContext);
    // 需要连到扬声器消费掉outputBuffer，process回调才能触发
    // 并且由于不给outputBuffer设置内容，所以扬声器不会播放出声音
    jsNode.connect(audioContext.destination);
    jsNode.onaudioprocess = onAudioProcess;
    // 把mediaNode连接到jsNode
    mediaNode.connect(jsNode);
    setjsNode(jsNode)
}
const [leftDataList] = useState([])
const [rightDataList] = useState([])
function onAudioProcess(event) {
    let audioBuffer = event.inputBuffer;
    let leftChannelData = audioBuffer.getChannelData(0),
        rightChannelData = audioBuffer.getChannelData(1);
    // 需要克隆一下
    leftDataList.push(leftChannelData.slice(0));
    rightDataList.push(rightChannelData.slice(0));
}
function createJSNode(audioContext) {
    const BUFFER_SIZE = 4096;
    const INPUT_CHANNEL_COUNT = 2;
    const OUTPUT_CHANNEL_COUNT = 2;
    // createJavaScriptNode已被废弃
    let creator = audioContext.createScriptProcessor || audioContext.createJavaScriptNode;
    creator = creator.bind(audioContext);
    return creator(BUFFER_SIZE,
        INPUT_CHANNEL_COUNT, OUTPUT_CHANNEL_COUNT);
}
function mergeArray(list) {
    let length = list.length * list[0].length;
    let data = new Float32Array(length),
        offset = 0;
    for (let i = 0; i < list.length; i++) {
        data.set(list[i], offset);
        offset += list[i].length;
    }
    return data;
}
// 交叉合并左右声道的数据
function interleaveLeftAndRight(left, right) {
    let totalLength = left.length + right.length;
    let data = new Float32Array(totalLength);
    for (let i = 0; i < left.length; i++) {
        let k = i * 2;
        data[k] = left[i];
        data[k + 1] = right[i];
    }
    return data;
}
function createWavFile(audioData) {
    const WAV_HEAD_SIZE = 44;
    let buffer = new ArrayBuffer(audioData.length * 2 + WAV_HEAD_SIZE),
        // 需要用一个view来操控buffer
        view = new DataView(buffer);
    // 写入wav头部信息
    // RIFF chunk descriptor/identifier
    writeUTFBytes(view, 0, 'RIFF');
    // RIFF chunk length
    view.setUint32(4, 44 + audioData.length * 2, true);
    // RIFF type
    writeUTFBytes(view, 8, 'WAVE');
    // format chunk identifier
    // FMT sub-chunk
    writeUTFBytes(view, 12, 'fmt ');
    // format chunk length
    view.setUint32(16, 16, true);
    // sample format (raw)
    view.setUint16(20, 1, true);
    // stereo (2 channels)
    view.setUint16(22, 2, true);
    // sample rate
    view.setUint32(24, 44100, true);
    // byte rate (sample rate * block align)
    view.setUint32(28, 44100 * 2, true);
    // block align (channel count * bytes per sample)
    view.setUint16(32, 2 * 2, true);
    // bits per sample
    view.setUint16(34, 16, true);
    // data sub-chunk
    // data chunk identifier
    writeUTFBytes(view, 36, 'data');
    // data chunk length
    view.setUint32(40, audioData.length * 2, true);

    // 写入PCM数据
    let length = audioData.length;
    let index = 44;
    let volume = 1;
    for (let i = 0; i < length; i++) {
        view.setInt16(index, audioData[i] * (0x7FFF * volume), true);
        index += 2;
    }
    return buffer;
}
function writeUTFBytes(view, offset, string) {
    var lng = string.length;
    for (var i = 0; i < lng; i++) {
        view.setUint8(offset + i, string.charCodeAt(i));
    }
}
const audios = useRef()
const SIZE = 1024 * 1024 * 10 //100MB
async function playRecord(arrayBuffer) {
    let blob = new Blob([new Uint8Array(arrayBuffer)], { type: "mp3" });
    console.log(blob, '[][][][][]');
    let blobUrl = URL.createObjectURL(blob);
    let files = new File([blob], "test.mp3", {
        type: "audio/mp3",
        lastModified: Date.now(),
    });
    if (!files) return
    //创建文件切片
    const createFileChunks = (files, size = SIZE) => {
        const fileChunks = []
        for (let cur = 0; cur < files.size; cur += size) {
            fileChunks.push(files.slice(cur, cur + size))
        }
        return fileChunks;
    }

    //上传切片
    const uploadFileChunks = async (fileChunks, filename) => {
        const formDataList = fileChunks.map((chunk, index) => {
            let formData = new FormData();
            formData.append('filename', filename);
            formData.append('hash', index);
            formData.append('chunk', chunk);
            return formData
        });
        const axiosList = formDataList.map((formDataItem) => {
            request.post('/JFChatMsg/upload', formDataItem).then(res => {
                console.log(res);
            })
        })

        //并发上传
        await Promise.all(axiosList)
    }

    //合并切片
    const mergeFileChunks = async (filename) => {
        console.log(filename, 'asfasg');
        request.post('/JFChatMsg/merge', { filename }).then(res => {
            //定义要发送的内容
            let objs = {
                to_id: props.location.state.toId,
                msg: res.data.url,
                headImg: "https://pic3.zhimg.com/80/v2-437f4dc41f0f972f31921a228641cf9e_720w.jpg?source=1940ef5c",
                name: props.location.state.remark
            }
            //向后台发送消息
            socket.send(objs)
        })
    }

    try {
        const fileChunks = createFileChunks(files)
        await uploadFileChunks(fileChunks, files.name)
        await mergeFileChunks(files.name)
        console.log('上传成功');
    } catch (error) {
        console.log('上传失败');
    }
    // upload(files, props)
    // //定义要发送的内容s
    // let objs = {
    //     to_id: props.location.state.toId,
    //     msg: blobUrl,
    //     headImg: "https://pic3.zhimg.com/80/v2-437f4dc41f0f972f31921a228641cf9e_720w.jpg?source=1940ef5c",
    //     name: props.location.state.remark
    // }
    // //向后台发送消息
    // socket.send(objs)
    //异步方法（解决实时更新问题）
    setTimeout(() => {
        getMessageList()
    }, 100)
    // document.querySelector('.audio-node').src = blobUrl;
    console.log(audios.current, '00000000');
}
function stopRecord() {
    // 停止录音
    mediaStream.getAudioTracks()[0].stop();
    jsNode.disconnect();
    mediaNode.disconnect()
    let leftData = mergeArray(leftDataList),
        rightData = mergeArray(rightDataList);
    console.log(leftData, rightData, '[]');
    let allData = interleaveLeftAndRight(leftData, rightData);
    let wavBuffer = createWavFile(allData);
    playRecord(wavBuffer);
}